package com.ll.domain.pk.biz.impl;

import com.ll.app.api.req.*;
import com.ll.base.dto.IdDTO;
import com.ll.base.dto.TenantAndIdDTO;
import com.ll.base.dto.TenantIdDTO;
import com.ll.base.enums.ResultCodeEnum;
import com.ll.base.exception.CustomRunTimeException;
import com.ll.base.util.ListUtil;
import com.ll.base.util.ScalarUtil;
import com.ll.dal.po.PkPO;
import com.ll.domain.pk.base.PkBaseService;
import com.ll.domain.pk.biz.PkDomainService;
import com.ll.domain.pk.convert.PkConvert;
import com.ll.domain.pk.dto.PkDTO;
import com.ll.domain.pk.enums.PkResultEnum;
import com.ll.domain.pk.enums.PkStatusEnum;
import com.ll.domain.pk.event.producer.AddPkEvent;
import com.ll.domain.pk.event.producer.UpdateResultPkEvent;
import com.ll.domain.pk.event.producer.UpdateStatusPkEvent;
import com.ll.domain.user.base.UserBaseService;
import com.ll.domain.user.dto.UserDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service
@RequiredArgsConstructor
public class PkDomainServiceImpl implements PkDomainService {

    private final PkBaseService pkBaseService;
    private final UserBaseService userBaseService;
    private final ApplicationEventPublisher applicationEventPublisher;


    @Override
    public void add(AddPkReqDTO pkDTO) {
        PkPO pkPO = PkConvert.addPkReqDTO2PO(pkDTO);

        //今天是否发起过挑战
        PkPO sourcePk = pkBaseService.getTodayPkBySourceId(pkDTO.getTenantId(), pkDTO.getSourceId());
        if (sourcePk != null) {
            throw new CustomRunTimeException(ResultCodeEnum.SOURCE_PK_TODAY_EXIST_ERROR);
        }

        //发起挑战者今天是否有挑战单
        List<PkPO> sourceList = pkBaseService.getPkIngById(pkDTO.getTenantId(), pkPO.getSourceId());
        if (ScalarUtil.isNotEmpty(sourceList)) {
            throw new CustomRunTimeException(ResultCodeEnum.SOURCE_PK_EXIST_ERROR);
        }

        //被挑战者今天是否被挑战过
        PkPO targetPk = pkBaseService.getTodayPkByTargetId(pkDTO.getTenantId(), pkDTO.getTargetId());
        if (targetPk != null) {
            throw new CustomRunTimeException(ResultCodeEnum.TARGET_PK_TODAY_EXIST_ERROR);
        }

        //被挑战者是否还有挑战记录未处理
        List<PkPO> targetPK = pkBaseService.getPkIngById(pkDTO.getTenantId(), pkPO.getTargetId());
        if (ScalarUtil.isNotEmpty(targetPK)) {
            throw new CustomRunTimeException(ResultCodeEnum.TARGET_PK_EXIST_ERROR);
        }

        //检验积分是否达到
        userBaseService.checkIntegral(Arrays.asList(pkDTO.getSourceId(), pkDTO.getTargetId()), pkDTO.getIntegral());

        //保持包
        pkBaseService.save(pkPO);

        //添加事件发起
        applicationEventPublisher.publishEvent(new AddPkEvent(PkConvert.PO2DTO(pkPO)));
    }

    @Override
    public void updateStatus(UpdateStatusPkReqDTO reqDTO) {
        PkPO pkPO = pkBaseService.getById(reqDTO.getId(), true);
        pkPO.checkCanUpdateStatus(true);

        PkPO newPO = PkPO.builder()
                .id(pkPO.getId())
                .status(reqDTO.getStatus())
                .build();
        if (PkStatusEnum.已拒绝 == reqDTO.getStatus()) {
            newPO.setResult(PkResultEnum.已拒绝);
        }
        pkBaseService.updateById(newPO);
        pkPO.setStatus(reqDTO.getStatus());


        //修改状态事件发起
        applicationEventPublisher.publishEvent(new UpdateStatusPkEvent(PkConvert.PO2DTO(pkPO)));

    }

    @Override
    public void updateResult(UpdateResultPkReqDTO reqDTO) {

        PkPO pkPO = pkBaseService.getById(reqDTO.getId(), true);
        pkPO.checkCanUpdateResult(true);
        pkPO.checkCanHandlerResult(reqDTO.getRefereeId(), true);

        PkPO newPO = PkPO.builder()
                .id(pkPO.getId())
                .result(reqDTO.getResult())
                .refereeId(reqDTO.getRefereeId())
                .build();
        pkBaseService.updateById(newPO);

        pkPO.setRefereeId(reqDTO.getRefereeId());
        pkPO.setResult(reqDTO.getResult());
        //修改返回结果事件发起
        applicationEventPublisher.publishEvent(new UpdateResultPkEvent(PkConvert.PO2DTO(pkPO)));
    }

    @Override
    public PkDTO getMyPk(TenantAndIdDTO dto) {
        ListPkReqDTO listDto = ListPkReqDTO.builder()
                .status(PkStatusEnum.发起中)
                .targetId(dto.getId())
                .build();
        listDto.setTenantId(dto.getTenantId());
        List<PkPO> pkPOList = pkBaseService.list(listDto);
        return  this.buildBizDTO(PkConvert.PO2DTO(ListUtil.first(pkPOList)));
    }

    @Override
    public List<PkDTO> list(ListPkReqDTO dto) {
        List<PkPO> pkPOList = pkBaseService.list(dto);
        return ListUtil.toList(pkPOList, r -> this.buildBizDTO(PkConvert.PO2DTO(r)));
    }

    public PkDTO buildBizDTO(PkDTO dto) {
        if (dto == null) {
            return null;
        }
        UserDTO sourceUser = userBaseService.getById(dto.getSourceId(), true);
        UserDTO targetUser = userBaseService.getById(dto.getTargetId(), true);
        dto.setSourceLogo(sourceUser.getLogo());
        dto.setSourceName(sourceUser.getUserName());
        dto.setTargetLogo(targetUser.getLogo());
        dto.setTargetName(targetUser.getUserName());
        return dto;
    }
}
